package com.eps.tesoreria.DAO;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.eps.DAO.SpringHibernateDAO;
import com.eps.TO.TipoTO;
import com.eps.entity.CentroCosto;
import com.eps.entity.Parametros;
import com.eps.entity.Proyecto;
import com.eps.entity.Tipo;
import com.eps.tesoreria.Entity.DetalleRendicionCajachica;
import com.eps.tesoreria.Entity.DetalleRendicionCajachicaPK;
import com.eps.tesoreria.Entity.FondofijoCajachica;
import com.eps.tesoreria.Entity.RendicionCajachica;
import com.eps.tesoreria.TO.DetalleRendicionCajaChicaTO;
import com.eps.tesoreria.TO.FondoFijoTO;
import com.eps.tesoreria.TO.RendicionCajaChicaTO;
import com.eps.util.Utiles_Convertir;


public class CajaChicaHibernateDAO extends HibernateDaoSupport implements
		ICajaChica {

	@Autowired
	private CajaChicaJdbcDAO cajajdbc;
	
	@Autowired
	private SpringHibernateDAO hdao;

	public TipoTO getTipoCampoCodigo(String campo, String codigo)
			throws Exception {
		Session session = getHibernateTemplate().getSessionFactory()
				.openSession();
		Query consulta = session
				.createSQLQuery(
						"SELECT id_tabla_tipo AS id_tabla_tipo, convert(varchar(25),tabla) AS tabla, convert(varchar(25), descripcion_campo) AS descripcion_campo, convert( varchar(10),codigo) AS codigo, descripcion_valor AS descripcion_valor FROM Tipo where ltrim(descripcion_campo)='"
								+ campo
								+ "' and ltrim(codigo)='"
								+ codigo
								+ "'").setResultTransformer(
						Transformers.aliasToBean(TipoTO.class));
		;
		return (TipoTO) consulta.list().get(0);
	}

	public boolean insertarRendicionCajaChica(RendicionCajaChicaTO rendicionto,String usuario)
			throws Exception {

		boolean retorno = false;
		Session session = getHibernateTemplate().getSessionFactory().openSession();
		
		BigDecimal monto_rendicion = BigDecimal.ZERO;
		Transaction tx = session.beginTransaction();
		tx.begin();
		try {
			List<DetalleRendicionCajaChicaTO> detallesTO = rendicionto.getDetalle().get("detalle");
			RendicionCajachica rendicion = new RendicionCajachica();
			rendicion.setIdRendicionCajaChica(rendicionto.getId_rendicion());
			rendicion.setIdFondofijo((FondofijoCajachica)session.get(FondofijoCajachica.class, rendicionto.getId_fondo_fijo()));
			rendicion.setFecha(new SimpleDateFormat("dd/MM/yyyy").parse(rendicionto.getFecha()));
			Parametros param = hdao.getParametrosIDNativo("TE1");
			rendicion.setAnio(param.getParam1());
			rendicion.setMes(param.getParam2());
			rendicion.setEstado(Utiles_Convertir.convertirToTipo_TipoTO(this.getTipoCampoCodigo("tipo_estado_cajachica", "01")));
			
			if (rendicionto.getId_rendicion() ==null || rendicionto.getId_rendicion().trim().length()==0) {
				String codigo = cajajdbc.getIdRendicionCaja(rendicion);
				System.out.println("<>" + codigo);
				rendicion.setIdRendicionCajaChica(codigo);
				session.persist(rendicion);
				List<DetalleRendicionCajachica> detalles = rendicion.getDetalleRendicionCajachicaList();
				int i = 0;
				for (DetalleRendicionCajaChicaTO detalleto : detallesTO) {
					i++;
					DetalleRendicionCajachica detalleRendicion = new DetalleRendicionCajachica();
					
					detalleRendicion.setDetalleRendicionCajachicaPK(new DetalleRendicionCajachicaPK(
									rendicion.getIdRendicionCajaChica(), i));
					detalleRendicion.setCodCentroCosto(detalleto.getCentroCostos());
					detalleRendicion.setIdCodPresupuestal(((CentroCosto) session.get(
							CentroCosto.class, detalleto.getCentroCostos())).getIdCodPresupuestal().getIdCodPresupuestal());
					detalleRendicion.setCodTrabajador(detalleto.getDni());
					detalleRendicion.setRucProveedor(detalleto.getRuc_proveedor());
					detalleRendicion.setCodUniOrganizativa(detalleto.getUnidad_organica());
					detalleRendicion.setCtaCble(detalleto.getCtaCtble());
					detalleRendicion.setFechaEmision(new SimpleDateFormat("dd/MM/yyyy").parse(detalleto.getFecha()));
					detalleRendicion.setGlosa(detalleto.getGlosa());
					detalleRendicion.setSerieCaja(detalleto.getSerie());
					detalleRendicion.setNumeroCaja(detalleto.getNumero());
					detalleRendicion.setIdproyecto(detalleto.getId_proyecto());
					detalleRendicion.setTipoDocumento(new Tipo(detalleto.getTipo_documento()));
					detalleRendicion.setPlantillaImpuesto(new Tipo(detalleto.getPlantilla_impuesto()));
					detalleRendicion.setTotal(detalleto.getMonto_total());
					detalleRendicion.setSubtotal(detalleto.getSub_total());
					detalleRendicion.setImpuesto(detalleto.getMonto_impuesto());
					detalleRendicion.setImpuestoNoGravado((detalleto.getMonto_otros() == null)?BigDecimal.ZERO:detalleto.getMonto_otros());
					
					
					if (detalleRendicion.getIdproyecto() != null && detalleRendicion.getIdproyecto().trim().length()!=0 ) {
						Proyecto p = (Proyecto) session.get(Proyecto.class,
								detalleRendicion.getIdproyecto());
						detalleRendicion.setIdCodInversion((p.getIdCodInversion() == null) ? null : p.getIdCodInversion().getIdCodInversion());
						detalleRendicion.setCtaCble(p.getIdCuentaContable().getIdCuentaContable());
					}
					monto_rendicion = monto_rendicion.add(detalleRendicion.getTotal());
					session.merge(detalleRendicion);
				}
			} else {
				  rendicion = getHibernateTemplate().get(RendicionCajachica.class, rendicionto.getId_rendicion());	
				  rendicion.setFecha(new SimpleDateFormat("dd/MM/yyyy").parse(rendicionto.getFecha()));
				int j = 0;
				List<DetalleRendicionCajachica> detalles_rendicion = getHibernateTemplate()
						.findByNamedQueryAndNamedParam(
								"DetalleRendicionCajachica.findByIdRendicionCajaChica",
								"idRendicionCajaChica",
								rendicion.getIdRendicionCajaChica());

				for (DetalleRendicionCajachica detalleRendicion : detalles_rendicion) {
					j++;
				}
				detalles_rendicion = rendicion.getDetalleRendicionCajachicaList();
				int i = 0;
				for (DetalleRendicionCajaChicaTO detalleto : detallesTO) {
					i++;
					DetalleRendicionCajachica detalleRendicion = new DetalleRendicionCajachica();
					
					detalleRendicion.setDetalleRendicionCajachicaPK(new DetalleRendicionCajachicaPK(
									rendicion.getIdRendicionCajaChica(), i));
					detalleRendicion.setCodCentroCosto(detalleto.getCentroCostos());
					detalleRendicion.setCodTrabajador(detalleto.getDni());
					detalleRendicion.setRucProveedor(detalleto.getRuc_proveedor());
					detalleRendicion.setCodUniOrganizativa(detalleto.getUnidad_organica());
					detalleRendicion.setCtaCble(detalleto.getCtaCtble());
					detalleRendicion.setFechaEmision(new SimpleDateFormat("dd/MM/yyyy").parse(detalleto.getFecha()));
					detalleRendicion.setGlosa(detalleto.getGlosa());
					detalleRendicion.setSerieCaja(detalleto.getSerie());
					detalleRendicion.setNumeroCaja(detalleto.getNumero());
					detalleRendicion.setIdproyecto(detalleto.getId_proyecto());
					detalleRendicion.setTipoDocumento(new Tipo(detalleto.getTipo_documento()));
					detalleRendicion.setPlantillaImpuesto(new Tipo(detalleto.getPlantilla_impuesto()));
					detalleRendicion.setTotal(detalleto.getMonto_total());
					detalleRendicion.setSubtotal(detalleto.getSub_total());
					detalleRendicion.setImpuesto(detalleto.getMonto_impuesto());
					detalleRendicion.setImpuestoNoGravado((detalleto.getMonto_otros() == null)?BigDecimal.ZERO:detalleto.getMonto_otros());
					
					
					if (detalleRendicion.getIdproyecto() != null && detalleRendicion.getIdproyecto().trim().length()!=0 ) {
						Proyecto p = (Proyecto) session.get(Proyecto.class,
								detalleRendicion.getIdproyecto());
						detalleRendicion.setIdCodInversion((p.getIdCodInversion() == null) ? null : p.getIdCodInversion().getIdCodInversion());
						detalleRendicion.setCtaCble(p.getIdCuentaContable().getIdCuentaContable());
					}
					monto_rendicion = monto_rendicion.add(detalleRendicion.getTotal());
					session.merge(detalleRendicion);
				}
				if (j > i) {
					for (int a = i + 1; a <= j; a++) {
						session.delete(session.get(
								DetalleRendicionCajachica.class,new DetalleRendicionCajachicaPK(rendicion.getIdRendicionCajaChica(), a)));
					}
					//session.flush();
				}
			}
			rendicion.setMontoRendicion(monto_rendicion);
			rendicion.setUsuario(usuario);
			
			rendicion.setFechaOperacion(new Date());
			
			session.merge(rendicion);
			FondofijoCajachica fondo = (FondofijoCajachica) session.get(FondofijoCajachica.class, rendicion.getIdFondofijo().getIdFondofijo());
			Tipo estado_fondo = Utiles_Convertir.convertirToTipo_TipoTO(this
					.getTipoCampoCodigo("tipo_estado_fondofijo", "02"));
			fondo.setEstado(estado_fondo);
			session.merge(fondo);
			session.flush();
			tx.commit();
			retorno = true;
		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback();
			throw e;
		}

		return retorno;
	}

	public boolean rendirCajaChica(String idRendicion, int idFondoFijo)
			throws Exception {
		// TODO Auto-generated method stub
		return false;
	}
	
	//tesoreria
	 public List<FondoFijoTO> getListaFondosFijosPorZona(String id_zona) throws Exception  {
		Session session = getHibernateTemplate().getSessionFactory()
				.openSession();
		Query consulta = session
				.createSQLQuery(
						"SELECT id_fondofijo, descripcion,convert(varchar(2),id_zona) AS id_zona , monto_base, estado FROM fondofijo_cajachica where id_zona='"+id_zona+"'").setResultTransformer(
						Transformers.aliasToBean(FondoFijoTO.class));
		return consulta.list();
	}
	 
	 public List<DetalleRendicionCajaChicaTO> getDetalleRendicionChica(String id_rendicion) throws Exception  {
			Session session = getHibernateTemplate().getSessionFactory()
					.openSession();
			Query consulta = session
					.createSQLQuery(
							" SELECT convert(varchar,drc.id_rendicion_caja_chica) as id_rendicion , drc.correlativo, drc.tipo_documento, t.descripcion_valor as desc_documento, rtrim(convert(varchar,drc.serie_caja)) as serie,rtrim(convert(varchar,drc.numero_caja))  as numero, CONVERT(varchar, drc.fecha_emision, 103) AS fecha,case when  len(drc.ruc_proveedor) =0  then convert(varchar,drc.cod_trabajador) else convert(varchar,drc.ruc_proveedor) end as codigo,rtrim(convert(varchar,drc.ruc_proveedor)) as ruc_proveedor, "
			                + " convert(varchar,drc.cod_trabajador)  as dni, drc.subtotal as sub_total, drc.impuesto as monto_impuesto,drc.impuesto_no_gravado as monto_otros, drc.total as monto_total,rtrim(convert(varchar,drc.cta_cble)) as ctaCtble,rtrim(convert(varchar,drc.Cod_CentroCosto)) as centroCostos, drc.glosa,rtrim(convert(varchar,drc.id_cod_presupuestal))  as codPresupuesta,rtrim(convert(varchar,drc.id_proyecto)) as id_proyecto,drc.plantilla_impuesto,  "
			                + " isnull((select razon_social from proveedor where cod_proveedor=drc.ruc_proveedor),'') as desc_proveedor,rtrim(convert(varchar,drc.cod_uni_organizativa)) as unidad_organica, "
			                + " isnull((select ap_paterno + ' ' + ap_materno + ' ' + nombre from persona where codigo_persona=drc.cod_trabajador),'')  as desc_trabajador, "
			                + " isnull((select rtrim(desc_cuenta) from cuenta_contable where id_cuenta_contable=drc.cta_cble),'') as desc_cuenta, "
							+ "	isnull(cast((select rtrim(unidad_organizativa) from unidad_organizativa where cod_uni_organizativa=drc.cod_uni_organizativa)as varchar),'') as desc_unidadorg, "
							+ "	isnull(cast((select centro_costo from centro_costo where cod_centrocosto=drc.cod_centrocosto)as varchar),'') as desc_cencosto, "
							+ "	isnull(cast((select rtrim(nom_proyecto) from proyecto where id_proyecto=drc.id_proyecto)as varchar),'') as desc_proyecto" 
			                + " FROM detalle_rendicion_cajachica AS drc "
			                + " INNER JOIN Tipo AS t ON drc.tipo_documento = t.id_tabla_tipo "
			                + " where drc.id_rendicion_caja_chica = '" + id_rendicion + "' order by drc.fecha_emision desc").setResultTransformer(
							Transformers.aliasToBean(DetalleRendicionCajaChicaTO.class));
			return consulta.list();
		}
	 
	 public List<RendicionCajaChicaTO> getRendicionesPorFondoFijo(int fondo_fijo) throws Exception  {
			Session session = getHibernateTemplate().getSessionFactory().openSession();
			Query consulta = session.createSQLQuery(
							" select convert(varchar,rc.id_rendicion_caja_chica) as id_rendicion,rc.id_fondofijo as id_fondo_fijo,convert(varchar(10),rc.fecha,103) as fecha,rc.referencia,rc.estado,convert(varchar(2), ff.id_zona) as id_zona ,ff.monto_base,rc.monto_rendicion,convert(decimal(10,2),round(rc.monto_rendicion*100/ff.monto_base,2)) as porcentaje_consumo,tipo.descripcion_valor as descripcion_estado"
			                + " from rendicion_cajachica rc inner join fondofijo_cajachica ff on rc.id_fondofijo=ff.id_fondofijo inner join tipo on tipo.id_tabla_tipo=rc.estado "
			                + " where rc.id_fondofijo = " + fondo_fijo + "  order by 1 desc").setResultTransformer(
							Transformers.aliasToBean(RendicionCajaChicaTO.class));
			return consulta.list();
		}
	 
	 public boolean verificaEdicionDeRendicion(String id_rendicion) throws Exception{
		 TipoTO tipo_sin_rendir = getTipoCampoCodigo("tipo_estado_cajachica", "01");
		 RendicionCajachica rendicion = getHibernateTemplate().get(RendicionCajachica.class, id_rendicion);
         return (rendicion.getEstado().getIdTablaTipo().intValue() == tipo_sin_rendir.getId_tabla_tipo().intValue()) ? true: false;
	 }
	 
	 public boolean rendirCajaChica(String id_rendicion) throws Exception{
		 TipoTO tipo_sin_rendir = getTipoCampoCodigo("tipo_estado_cajachica", "01");
		 RendicionCajachica rendicion = getHibernateTemplate().get(RendicionCajachica.class, id_rendicion);
        if(rendicion.getEstado().getIdTablaTipo().intValue() == tipo_sin_rendir.getId_tabla_tipo().intValue()) {
        	Parametros param =hdao.getParametrosIDNativo("TE3");
            BigDecimal porcentaje_maximo = param.getParam7();
            
            param = hdao.getParametrosIDNativo("TE1");

            if ((rendicion.getMontoRendicion().multiply(new BigDecimal(100)).divide(rendicion.getIdFondofijo().getMontoBase(),2, RoundingMode.HALF_UP).compareTo(porcentaje_maximo) > 0)) {
            	Session session = getHibernateTemplate().getSessionFactory().openSession();
				Transaction tx = session.beginTransaction();
				tx.begin();
				try {
					Tipo tipo_noAtendido = Utiles_Convertir.convertirToTipo_TipoTO(hdao.getTipoCampoCodigo("tipo_estado_cajachica", "02"));
					rendicion.setEstado(tipo_noAtendido);
					rendicion.setMesRendicion(param.getParam2());
					rendicion.setAnioRendicion(param.getParam1());
	                session.merge(rendicion);
	                
	                FondofijoCajachica fondo = rendicion.getIdFondofijo();
	                Tipo estado_fondo = Utiles_Convertir.convertirToTipo_TipoTO(hdao.getTipoCampoCodigo("tipo_estado_fondofijo", "03"));
	                fondo.setEstado(estado_fondo);
	                session.merge(fondo);
	                
					session.flush();
					tx.commit();
				} catch (Exception e) {
					e.printStackTrace();
					tx.rollback();
					throw e;
				}
            }
            else
            	throw new Exception("EL MONTO A RENDIR ES INSUFICIENTE");
        }
        else 
            throw new Exception("NO SE ADMITE RENDIR ");
        return true;
	 }
	 
	 public boolean aperturarCajaChica(int id_fondofijo) throws Exception{
		 //TipoTO t1 = getTipoCampoCodigo("id_fondofijo", "01");
		 FondofijoCajachica fondo = getHibernateTemplate().get(FondofijoCajachica.class,id_fondofijo);
		 TipoTO t2 = getTipoCampoCodigo("tipo_estado_fondofijo", "02");
		 TipoTO t3 = getTipoCampoCodigo("tipo_estado_fondofijo", "03");
        if(fondo.getEstado().getIdTablaTipo().intValue() == t2.getId_tabla_tipo().intValue())
            throw new Exception("EXISTE UNA RENDICION VIGENTE");
        else if(id_fondofijo == t3.getId_tabla_tipo().intValue())
            throw new Exception("EL FONDO FIJO NO ESTA DISPONIBLE ACTUALMENTE");
        return true;
	 }

}
